package com.kingtao.rpc;

import com.kingtao.entry.LogEntry;
import com.kingtao.enums.NodeStatusEnums;
import com.kingtao.message.*;
import com.kingtao.protocol.MessageCodec;
import com.kingtao.protocol.ProtocolFrameDecoder;
import com.kingtao.service.Impl.NodeGroupServiceImpl;
import com.kingtao.session.GroupSessionImpl;
import com.kingtao.util.CoreData;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.List;


/**
 * @Author: kingtao
 * @Date: 2023-08-31-11:35
 * @Description:
 */
@Slf4j
public class TestServer {
    public static List<LogEntry> logEntries;
    public static NodeGroupServiceImpl groupService;
    public static GroupSessionImpl groupSession;

    public static void main(String[] args) {
        runServer();
    }

    public static void runServer() {
        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        LoggingHandler LOGGING_HANDLER = new LoggingHandler(LogLevel.DEBUG);
        MessageCodec CODEC_HANDLER = new MessageCodec();

        ServerBootstrap server = new ServerBootstrap();
        server.group(boss,worker)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel channel) throws Exception {
                        channel.pipeline().addLast(new ProtocolFrameDecoder());
                        channel.pipeline().addLast(LOGGING_HANDLER);
                        channel.pipeline().addLast(CODEC_HANDLER);
                        //  信息同步
                        channel.pipeline().addLast(new SimpleChannelInboundHandler<GroupSessionRequest>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, GroupSessionRequest request) throws Exception {
                                groupSession = request.getGroupSession();
//                                log.debug("groupSession：{}", groupSession);
                            }
                        });
                        //  共识
                        channel.pipeline().addLast(new SimpleChannelInboundHandler<ServerInitRequest>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, ServerInitRequest msg) throws Exception {
                                log.debug("");
                                int leaderId = msg.getLeaderId();
                                int secondLeaderId = msg.getSecondLeaderId();
                                if (msg.getLeaderId() == msg.getGroup().getLeaderId() && msg.getGroup().getSecondLeaderId() == secondLeaderId) {
                                    ctx.writeAndFlush(new ServerInitResponse(leaderId, secondLeaderId, true));
                                }else {
                                    ctx.writeAndFlush(new ServerInitResponse(leaderId, secondLeaderId, false));
                                }
                            }
                        });
                        //  新增节点
                        channel.pipeline().addLast(new SimpleChannelInboundHandler<AppendNodeResponse>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, AppendNodeResponse response) throws Exception {
                                if (response.isSuccess()) {
                                    log.debug("Node {} 添加成功", response.getId());
                                }else {
                                    log.debug("Node {} 添加失败", response.getId());
                                }
                            }
                        });
                        //  leader 写入
                        channel.pipeline().addLast(new SimpleChannelInboundHandler<AppendLeaderLogEntryResponse>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, AppendLeaderLogEntryResponse response) throws Exception {
                                log.debug("{}", response.getStr());
                            }
                        });
                        //  secondLeader 写入
                        channel.pipeline().addLast(new SimpleChannelInboundHandler<AppendSecondLeaderLogEntryResponse>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext context, AppendSecondLeaderLogEntryResponse response) throws Exception {
                                log.debug("{}", response.getStr());
                            }
                        });
                        //  followerLeader 写入
                        channel.pipeline().addLast(new SimpleChannelInboundHandler<AppendFollowLeaderLogEntryResponse>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, AppendFollowLeaderLogEntryResponse response) throws Exception {
                                log.debug("{}", response.getString());
                            }
                        });
                        //  follower 写入
                        channel.pipeline().addLast(new SimpleChannelInboundHandler<AppendFollowerLogEntryResponse>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, AppendFollowerLogEntryResponse response) throws Exception {
                                log.debug("{}", response.getString());
                            }
                        });
                        channel.pipeline().addLast(new SimpleChannelInboundHandler<GroupServiceRequest>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext context, GroupServiceRequest request) throws Exception {
                                log.debug("node"+request.getId()+" : "+request.getString());
                            }
                        });
                        //  心跳检测
                        channel.pipeline().addLast(new IdleStateHandler(1, 0, 0));
                        //  入栈出栈 处理器
                        channel.pipeline().addLast(new ChannelDuplexHandler() {
                            //  用来触发特殊事件
                            @Override
                            public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                                IdleStateEvent event = (IdleStateEvent) evt;
                                if (event.state() == IdleState.READER_IDLE) {
                                    if (groupService.isCreateGroup() == false) {
                                        log.debug("leader id: {},secondLeader id: {}", groupService.getLeader().getId(), groupService.getSecondLeader().getId());
                                    } else {
                                        log.debug("leader id: {},secondLeader id: {}, followerLeader id: {}",
                                                groupService.getLeader().getId(), groupService.getSecondLeader().getId(), groupService.getNodeGroup().getFollowerLeaderIdMap());
                                    }
                                    if (groupService.getLeader().getStatus() != NodeStatusEnums.leader
                                            && groupService.getSecondLeader().getStatus() != NodeStatusEnums.secondLeader) {
                                        log.debug("leader与secondLeader出现问题,重新选择");
                                        groupService.setLeader();
                                    } else if (groupService.getSecondLeader().getStatus() != NodeStatusEnums.secondLeader) {
                                        log.debug("secondLeader出现问题,重新选择");
                                        groupService.setSecondLeader();
                                    }
                                    else if (groupService.getLeader().getStatus() != NodeStatusEnums.leader) {
                                        log.debug("leader出现问题,重新选择");
                                        groupService.setLeader();
                                    }
                                }
                            }
                        });

                    }
                });

        try {
            ChannelFuture future = server.bind(CoreData.NODE_INIT_PORT).sync();
            future.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }
}
